home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CMARS.ZIP / CAMARS.ASM next >
Assembly Source File  |  1995-07-20  |  41KB  |  1,589 lines

  1. ;
  2. ; CAMARS.ASM
  3. ;
  4. ; Notes:
  5. ;
  6. ;   I rolled the horizontal and vertical draw routines into loops for clarity
  7. ;
  8. ;  I moved the whole main program over to the C code.
  9. ;
  10. ;  I added rotate code.  It uses an incremental algorithm similar to
  11. ;  bresenhams line formula to calculate points on the first 45 degree
  12. ;  arc of a circle, then reflects the points calculated into whatever
  13. ;  quadrants are being viewed.  It uses the points generated to sample
  14. ;  the mountain map and draw the heights.  This is faster than simply
  15. ;  applying the rotation formula directly.
  16. ;
  17. ;  programmer:
  18. ;    Original code, unknown
  19. ;    De-optimized (clarified code) and rotation modifications:
  20. ;        David Lindauer, e-mail gclind01@ulkyvx.louisville.edu
  21. ;        July 19, 1995
  22. ;
  23.         .386
  24.  
  25.         Jumps
  26.  
  27.     extrn sintable : word, costable: word, _B : word
  28.  
  29.     PUBLIC _FadeOut, _FadeIn, _ClearPAL, _ReadPalette, _PaletteOut
  30.     PUBLIC _MakeMakeTable, _MakeMarsPalette, _InitRandom
  31.     PUBLIC _DrawView,_CalcFractal
  32.     PUBLIC    _CalcSky, _CalcMountains, _UpdateViewCoord
  33.     PUBLIC    _UpdateSky, _UpdateMountains
  34.     PUBlIC _SwitchToText, _SwitchToGraphics, _RetFARData, _DeltaMove
  35.     PUBLIC _ReleaseFarData
  36.  
  37.     PUBLIC _Map_Seg, _Color_Seg,_Sky_Seg,_InternalScreen_Seg
  38.     PUBlIC    _MapMakeTable,_AddCXTable,_AddDXTable, _MapCoord
  39.     PUBLIC _MountHeight, _Map_X, _Map_Y, _RandomSeed
  40.     PUBLIC    _BiosPal, _MarsPal, _W_Divider, _Count_Loop
  41.     
  42.     PUBLIC  _FlyHeight, _Angle
  43.  
  44. SkyPalette = 64
  45. MountainPalette = 0
  46. MidbandPalette = 128
  47. NullPalette = 192
  48.  
  49. ;
  50. ; Paragraph offsets into the 256Kb extra memory we are going to alloc
  51. ;
  52. MapAOFFS = 0
  53. MapBOFFS = 1000h
  54. SkyOFFS = 2000h
  55. InternalScreenOFFS = 3000h
  56.  
  57.  
  58. _DATA    SEGMENT DWORD PUBLIC USE16 'DATA'
  59.  
  60. _Map_Seg        dw      MapAOFFS
  61. _Color_Seg        dw      MapBOFFS
  62. _Sky_Seg         dw      SkyOFFS
  63. _InternalScreen_Seg    dw    InternalScreenOFFS
  64. _MapMakeTable    dw      41 dup (0000h), 10 dup (0001h), 09 dup (0003h)
  65. LastMake        dw      0003h, 0000h
  66. _AddCXTable      dw       16, -16, -8, 32
  67. _AddDXTable      dw      -32, -32, 16, 32
  68. _MapCoord        dw      0000h, 0004h, 0202h, 0FEFFh   ;0,4,514,65279 decimal
  69. VRAM_Seg        dw      0A000h        ; VGA memory
  70. baseangles    dw    255,128,127,0,-1,-128,-129,-256,-257,-384,-385,-512
  71. AngleConv    dw    4096/360      ; 512/360*8
  72. ;
  73. ; reflection bits, used to reflect bits from first octant into other
  74. ; ll octants as needed
  75. ;
  76. reflectswap    dw    0000011001100110b
  77. reflectnegx    dw    0000110000111100b
  78. reflectnegy    dw    0000000011110000b
  79. _W_Divider       dw      0DB97h        ; 56215 decimal, controls the mountain
  80.                     ; density .. the bigger the more 
  81. _MountHeight    dw    0
  82. _Map_X        dw    0
  83. _Map_Y        dw    0
  84. _RandomSeed    dw    0
  85. PerspectiveIndex    dw    0
  86. RelativeHeight    dw    0
  87. ReciprocalPerspective    dw    0
  88. CurrentCol    dw    0
  89. _Count_Loop    dw    0
  90. _Angle        dw    0
  91. _NormAngle    dw    0
  92. angletab    dw    12 DUP (0)
  93. intermedangletab dw    5 DUP (0)
  94. octant        dw    0
  95. Table_A        dw    256 Dup (0)
  96. Table_B        dw    256 Dup (0)
  97. _BiosPal    db    256 *3 Dup (0)
  98. _MarsPal    db    256 *3 Dup (0)
  99. TempPal        db    256 *3 Dup (0)
  100.  
  101. _FlyHeight    db    0
  102.  
  103.     align 4
  104. SkyMountHeight    dd    0
  105. SkyX    dd    0
  106. SkyY    dd    0
  107. D        dd    0
  108. Xrel        dd    0
  109. Yrel        dd    0
  110. Xpos        dd    0
  111. Ypos        dd    0
  112. RfourthCsquared    dd    0
  113. TwoRfourthCsquared    dd    0
  114. RC        dd    0
  115. DeltaX        dd    0
  116. DeltaY        dd    0
  117.  
  118. _DATA    ENDS
  119.  
  120.  
  121.  
  122. _TEXT     SEGMENT WORD PUBLIC USE16 'CODE'
  123.     assume cs:_TEXT, ds:_DATA, es:nothing,fs:nothing,gs:nothing
  124. ;--------------------------Miscellaneous subroutines-------------------
  125.  
  126. ;
  127. ; Return the map data segments
  128. ;
  129. ; prototype: unsigned RetFARData(void)
  130. ;
  131. _RetFARData    proc    far
  132.         mov ah,48h    ; Allocate memory func
  133.         mov bx,4000h    ; Allcoate 4096 paragraphs, or 64K
  134.         int 21h        ; Allocate the memory
  135.         jc not_allocated ; Error if couldn't complete
  136.         ret
  137.  not_allocated:
  138.         mov ax, 0
  139.         ret
  140. _RetFARData    endp
  141. ;
  142. ; Release data area
  143. ;
  144. ; prototype: void ReleaseFarData(unsigned seg)
  145. ;
  146.         thefarseg = bp+6
  147. _ReleaseFarData    proc    far
  148.         push    bp
  149.         mov    bp,sp
  150.         mov    bx,[thefarseg]
  151.         mov    ah,49h
  152.         int    21h
  153.         pop    bp
  154.         ret
  155. _ReleaseFarData    endp
  156.  
  157. ;
  158. ; Wait for Vertical retrace to go high, then low
  159. ; i.e. sync with start of display
  160. ;
  161. ; Modifies: dx,al
  162. ;
  163. WaitVRT       proc    near
  164.                 mov     dx, 03DAh       ; Input status reg #1
  165.   @wv1:
  166.                 in      al, dx          ; While Vertical Retrace is low
  167.                 test    al, 8           ;
  168.                 jz      @wv1           ;
  169.   @wv2:
  170.                 in      al, dx          ; Loop while retrace is high
  171.                 test    al, 8           ;
  172.                 jnz     @wv2           ;
  173.         ret
  174. WaitVRT    endp
  175. ;
  176. ; Draw a palette to palette mem
  177. ;
  178. ; Input regs:
  179. ;    si = palette to draw
  180. ;
  181. ; Modifies: dx,al
  182. ;
  183. PaletteOut    proc     near
  184.         push    si
  185.                 call    WaitVRT            ;
  186.         cli
  187.                 mov     cx, 3*256       ;
  188.                 mov     dx, 03C8h       ; Set beginning of palette regs
  189.                 mov     al, 00h         ;
  190.                 out     dx, al          ;
  191.                 inc     dx              ; Point to palette data reg
  192.                 rep     outsb           ; Output the palette
  193.         sti
  194.                 call    WaitVRT
  195.         pop    si
  196.         ret
  197. PaletteOut    endp
  198. ;
  199. ; Shell for calling palette out routine from C
  200. ;
  201. _PaletteOut    proc    far
  202.         palette = dword ptr [bp+6]
  203.         push    bp
  204.         mov    bp,sp
  205.         push    si
  206.         push    ds
  207.         lds    si,[palette]
  208.         call    PaletteOut
  209.         pop    ds
  210.         pop    si
  211.         pop    bp
  212.         ret
  213. _PaletteOut    endp
  214. ;
  215. ; Fade out.
  216. ;
  217. ; Input regs:
  218. ;    si = palette to fade
  219. ; modifies: dx,ax,bx,cx,di  
  220. ;
  221. ; prototype:  void fadeout(BYTE *table);
  222. ;
  223. _FadeOut    proc far
  224.         table = dword ptr [bp + 6]
  225.         push    bp
  226.         mov    bp,sp
  227.         push    ds
  228.         push    si
  229.         push    di
  230.         
  231.         
  232.         push    ds
  233.         pop    es
  234.               mov     bx, 0200h    ; BH = increment, bl = current color compare
  235.   @fo1:
  236.         lds    si,[table]
  237.         
  238. ;
  239. ; Blank out any entry that is less than color compare
  240. ;
  241.                 mov     cx, 3*256       ; 256 palette entries, 3 colors/palette
  242.         mov    di,offset TempPal
  243.   @fo2:        
  244.                 lodsb                   ; if source < color compare
  245.                 sub     al, bl
  246.                 cmc
  247.                 sbb     ah, ah          ; use 0
  248.                 and     al, ah          ; Else use color
  249.                 stosb                   ; To dest
  250.  
  251.                 loop    @fo2
  252. ;
  253. ; Draw the palette
  254. ;
  255.         push    es
  256.         pop    ds
  257.         mov    si,offset TempPal
  258.         call    PaletteOut
  259. ;
  260. ; Loop if not done
  261. ;
  262.                 add     bl, bh          ; Next color compare
  263.                 test    bl, 3Fh         ; Only 63 intensities
  264.                 jnz     @fo1
  265.         pop    di
  266.         pop    si
  267.         pop    ds
  268.         pop    bp
  269.         ret
  270. _FadeOut        ENDP
  271.  
  272. ; Fade in
  273. ;
  274. ; input regs:
  275. ;    si = palette to fade
  276. ;
  277. ; modifies: ax,bx,cx,dx,di
  278. ;
  279. ; prototype: void FadeIn(BYTE *table)
  280. _FadeIn         proc    far
  281.         table = dword ptr [bp + 6]
  282.         push    bp
  283.         mov    bp,sp
  284.         push    ds
  285.         push    si
  286.         push    di
  287.  
  288.         push    ds
  289.         pop    es
  290.                 mov     bx, 0FE40h    ; bh = increment, bl = color compare
  291.   @fi1:
  292.         lds    si,[table]
  293.         mov    di,offset TempPal
  294. ;
  295. ; Blank out any color less than color compare
  296. ;
  297.                mov     cx, 3*256    ;
  298.   @fi2:
  299.                 lodsb            ; if source < color compare
  300.                 sub     al, bl        ;
  301.                 cmc            ;
  302.                 sbb     ah, ah        ; use 0
  303.                 and     al, ah        ; Else use color
  304.                 stosb            ;
  305.                 loop    @fi2
  306. ;
  307. ; Output the palette
  308. ;
  309.         push    ds
  310.         pop    es
  311.         mov    si,offset TempPal
  312.         call    PaletteOut
  313.                 add     bl, bh        ; Next color compare
  314.                 test    bl, 3Fh
  315.                 jnz     @fi1
  316.         pop    di
  317.         pop    si
  318.         pop    ds
  319.         pop    bp
  320.         ret
  321. _FadeIn        ENDP
  322.  
  323. ;
  324. ; Clear palette
  325. ;
  326. ; Modifies: si,eax,cx,dx
  327. ;
  328. ;prototype: void ClearPAL(void);
  329. ;
  330. _ClearPAL      proc far
  331.         push    si
  332.         push    di
  333.         push    ds
  334.         pop    es
  335.         mov    di,offset TempPal
  336.         sub    eax,eax
  337.         mov    cx,768/4
  338.         rep    stosd
  339.         mov    si,offset TempPal
  340.          call    PaletteOut
  341.         pop    di
  342.         pop    si
  343.         ret
  344. _ClearPAL    endp
  345.  
  346. ;
  347. ; Read a palette in using bios
  348. ;
  349. ; input: 
  350. ;    dx = palette offset
  351. ;
  352. ; modifies: es,bx,cx,ax
  353. ;
  354. ; prototype: ReadPalette(BYTE *table)
  355. ;
  356. ;
  357. _ReadPalette        proc far    
  358.         table = dword ptr [bp + 6]
  359.         push    bp
  360.         mov    bp,sp
  361.         push    ds
  362.         push    ds
  363.         pop    es
  364.         lds    dx,[table]
  365.                 xor     bx, bx
  366.                 mov     cx, 256            ; read block of color registers
  367.                 mov     al, 17h            ; into TempPAL1
  368.                 mov     ah, 10h
  369.                 int     10h
  370.         pop    ds
  371.         pop    bp
  372.         ret
  373. _ReadPalette        endp
  374.     
  375. ;
  376. ; Switch to graphics mode
  377. ; modifes: ax
  378. ;
  379. ; prototype: void SwitchToGraphics(void)
  380. _SwitchToGraphics proc far
  381.                 mov     al, 13h            ; Set 320x200 graphics mode
  382.                 mov     ah, 00h
  383.         int    10h
  384.         ret
  385. _SwitchToGraphics endp
  386. ;
  387. ; Switch to text mode
  388. ;
  389. ; modifies: ax
  390. ;
  391. ; prototype: void SwitchToText(void)
  392. _SwitchToText    proc    far
  393.                 mov     al, 03h        ; Put us in text mode
  394.                 mov     ah, 00h
  395.                 int     10h             ; Switch Back to Char Mode
  396.         ret
  397. _SwitchToText    endp
  398. ;
  399. ; Make the map make table
  400. ;
  401. ; modifies ax,cx,di,es
  402. ;
  403. ; prototype: void MakeMakeTable(void)
  404. ;
  405. _MakeMakeTable    proc    far
  406.         push    di
  407.         push    ds
  408.         pop    es
  409.         mov    di,offset _MapMakeTable
  410.         mov    ax,0ffffh
  411.                 mov     cx, (offset LastMake-offset _MapMakeTable)/2+1    ; Size of map make table
  412.   @Decompress2:
  413.                 add     ax, [di]    ; ax = ax + value  in table +1
  414.                 inc     ax        ;
  415.                 stosw            ; Value in table = ax
  416.                 loop    @Decompress2    ; until CX = 0
  417.         pop    di
  418.         ret
  419. _MakeMakeTable    endp
  420. ;
  421. ; Make the palette for the prog
  422. ;
  423. ; modifies: everything
  424. ;
  425. ; Prototype: void MakeMarsPalette(void)
  426. ;
  427. _MakeMarsPalette    PROC    far
  428.         push    si
  429.         push    di
  430.          mov    di,offset _MarsPal
  431.         mov    si,di
  432.         sub    ax,ax
  433.         mov    cx,64
  434. @map:
  435. ;
  436. ; Mountain palette entry
  437. ; ( gray scale)
  438. ;
  439.         mov    [di],al
  440.         mov    [di+1],al
  441.         mov    [di+2],al
  442. ;
  443. ; Sky palette entry
  444. ; (blue scale)
  445. ;
  446.         mov    byte ptr [di + SkyPalette*3],0
  447.         mov    byte ptr [di + SkyPalette*3+1],0
  448.         mov    [di + SkyPalette*3+2],al
  449. ;
  450. ; Midband palette entry
  451. ; (green scale)
  452. ;
  453.         mov    byte ptr [di + MidbandPalette*3],0
  454.         mov    [di + MidbandPalette*3+1],al
  455.         mov    byte ptr [di + MidbandPalette*3+2],0
  456. ;
  457. ;Null palette, unused
  458. ;
  459.         mov    byte ptr [di + NullPalette*3],0
  460.         mov    byte ptr [di + NullPalette*3+1],0
  461.         mov    byte ptr [di + NullPalette*3+2],0
  462.         inc    al
  463.         inc    di
  464.         inc    di
  465.         inc    di
  466.         loop    @map
  467.         call    PaletteOut
  468.         pop    di
  469.         pop    si
  470.         ret
  471. _MakeMarsPalette    ENDP
  472. ;
  473. ; Init random # generator
  474. ;
  475. ; modifies ax,dx
  476. ;
  477. ;prototype: void InitRandom(void)
  478. ;
  479. _InitRandom    proc    far
  480.                 xor     ax, ax
  481.                 int     1Ah            ; get CLOCK value in DH
  482.                 and     dh, 7Fh
  483.                 mov     dx, 7FCFh               ; preset RND seed in DX
  484.                 mov     [_RandomSeed], dx
  485.         ret
  486. _InitRandom    endp
  487. ;
  488. ; Get a random number
  489. ;
  490. ; input:
  491. ;    si = seed
  492. ; output:
  493. ;    si = dx = random #
  494. ; Modifies: ax,si,dx
  495. ;
  496. RandomNumber    proc    near
  497.                 mov     ax, 0AFh    ; 175 decimal
  498.                 mul     si
  499.                 add     ax, 2BC0h    ; 11200 decimal
  500.                 adc     dx, 0
  501.                 div     [_W_Divider]
  502.                 mov     si, dx
  503.         ret
  504. RandomNumber    endp
  505. ;
  506. ; Draw a view
  507. ;
  508. ; modifies: es,si,ax,di,bl,cx
  509. ;
  510. ; prototype: void DrawView(void)
  511. _DrawView    proc    far
  512.         push    ds
  513.         push    si
  514.         push    di
  515.                 mov     es, [VRAM_Seg]        
  516.         sub    si,si
  517.         mov    ax, [_InternalScreen_Seg]
  518.         mov    ds,ax
  519.                 mov     di, (320-256)/2        ; Center image horizontally
  520.                 mov     bl, 200            ; 200 lines
  521.                         ; Actual image is 256 * 200
  522.   @Copy2VRAM:
  523.                 mov     cx, 256/4        ; Draw a line
  524.                 rep     movsd            ;
  525.                 add     di, (320-256)        ; Move to start of next line 
  526.         dec    bl            ;
  527.                 jnz     @Copy2VRAM        ; Draw whole screen
  528.         pop    di
  529.         pop    si
  530.         pop    ds
  531.         ret
  532. _DrawView    endp
  533. ;---------------------------Calculation and view routines---------------
  534. ;
  535. ; Using Fractals to generate the terrain.  Nifty neeto I always wanted
  536. ; to know how this was done!
  537. ;
  538. ; The map this generates is 256x256.  Each byte generated is a height
  539. ;
  540. ; This routine takes a square of arbitrary size, and calculates the height
  541. ; of the midpoints of each line joining the corners using a combination
  542. ; of the average height of the corners and a psuedo-random algorithm.
  543. ; Then it calculates the height of the center point by averaging the four
  544. ; midpoints and applying the psuedo-random generator.  Then it uses
  545. ; Recursion to do the same thing to each of the four squares so generated.
  546. ; Each of these squares is then recursed into 4 more squares, until all
  547. ; bytes in the array are filled in.
  548. ;
  549. ; Randomize the average height
  550. ; For large cl this gives us a random number which can vary
  551. ; significantly from the midpoint.  For smaller cl the variance will be
  552. ; smaller.  Thus local maxima and minima will be maintained
  553. ;
  554. ; Randomize Average Height
  555. ;
  556. ; Modifies ax,si,dx,ch
  557. ;
  558. ; input:
  559. ;    cl = granularity
  560. ;    si = random number seed
  561. ;    al = number to randomize
  562. ; output:
  563. ;    al = randomized value
  564. ;
  565. RandomizeAvgHeight   proc    near
  566.         mov    ch,al
  567.         call    RandomNumber
  568.                 sub     dx, 67E8h ; Magic number, what's it do to random #
  569.                 xor     ax, ax    ; dx = ((cl *8 *rn)/10000h ) + avg heigh
  570.                 mov     al, cl
  571.                 shl     ax, 3
  572.                 imul    dx
  573.                 xor     ax, ax
  574.                 add     dl, ch  ;
  575.                 mov     ch, al  ; ch = 0
  576.                 adc     dh, ch  ;
  577.                 js      @CS2   ; If dh <0 use 0
  578.                 jz      @CS1    ; if dh =0 use dl
  579.                 ; Else dh >0use 0feh
  580.                 mov     dl, 0FEh
  581.   @CS1:        
  582.                 mov     al, dl
  583.   @CS2:                ; Else if dh = 0 use 0
  584.         ret
  585. RandomizeAvgHeight    endp
  586. ;
  587. ; Get the average height between two points & randomize it
  588. ;
  589. ; modifies: ax,bx,ch,dx,di
  590. ;
  591. ; input:
  592. ;    di = buffer pos to write to
  593. ;    al = first height
  594. ;    bx = position of second height
  595. ;
  596. RandomizeMidpoint    proc    near
  597.                 cmp     byte ptr es:[di], 0FFh ; Don't draw over what is there
  598.                 jne     @CS3
  599.                 add     al, es:[bx] ; Average current height and old height
  600.                 adc     ah, ch
  601.                 shr     ax, 1
  602.                 call    RandomizeAvgHeight   ; Calc
  603.                 stosb           ; Save the height we got by randomizing the average
  604.   @CS3:
  605.         ret
  606. RandomizeMidpoint    endp
  607.  
  608. ;
  609. ; Fractalize a 256x256 map
  610. ;
  611. ; Modifies: everything
  612. ;
  613. CalcFrac    proc    near
  614.                 shr     cx, 1
  615.                 jz      OutCalcFrac    ; Quit when the granularity is too thin
  616. ;
  617. ; First we calculate the height at the halfway pt at each side of the square
  618. ;
  619.                 xor     ax, ax
  620.                 add     al, es:[bx]    ;al = map byte
  621.                 adc     ah, ch          ; NOP
  622.                 add     bl, cl        ; Load DI up with halfway point
  623.                 mov     di, bx          ; 
  624.                 add     bl, cl        ; Move to another corner of square
  625.                 call    RandomizeMidpoint        ; Fill in the midpoint
  626.                 xor     ax, ax
  627.                 add     al, es:[bx]    ; al = height here at new bx
  628.                 adc     ah, ch        ; nop
  629.                 add     bh, cl        ; Load DI up with halfway point
  630.                 mov     di, bx
  631.                 add     bh, cl          ; Move to another corner of square
  632.                 call    RandomizeMidpoint        ; Fill in the midpoint
  633.                 xor     ax, ax        ; Contine to next corner of square
  634.                 add     al, es:[bx]
  635.                 adc     ah, ch
  636.                 sub     bl, cl
  637.                 mov     di, bx
  638.                 sub     bl, cl
  639.                 call    RandomizeMidpoint
  640.                 xor     ax, ax        ; And now work back to origin of square
  641.                 add     al, es:[bx]
  642.                 adc     ah, ch
  643.                 sub     bh, cl
  644.                 mov     di, bx
  645.                 sub     bh, cl
  646.                 call    RandomizeMidpoint
  647. ;
  648. ; Now we average all the halfway values
  649. ;
  650.                 xor     ax, ax
  651.                 add     al, es:[bx]
  652.                 adc     ah, ch
  653.                 add     bl, cl
  654.                 add     bl, cl
  655.                 add     al, es:[bx]
  656.                 adc     ah, ch
  657.                 add     bh, cl
  658.                 add     bh, cl
  659.                 add     al, es:[bx]
  660.                 adc     ah, ch
  661.                 sub     bl, cl
  662.                 sub     bl, cl
  663.                 add     al, es:[bx]
  664.                 adc     ah, ch
  665.                 shr     ax, 2
  666.                 call    RandomizeAvgHeight        ; Randomize it
  667.                 add     bl, cl        ; Move to midpoint of square
  668.                 sub     bh, cl
  669.                 mov     es:[bx], al    ; Fill it in
  670. ;
  671. ; Now we use recursion to handle the four squares we have subdivided into
  672. ;
  673. ; i.e. we are going to calculate the height at the midpoint of each
  674. ; side of each square.  Since we are using recursion that will recurse
  675. ; into the height at the midpoint of each of the 16 squares we generate
  676. ; And so on.  The check at the beginning of this function checks for
  677. ; byte granularity; when we hit that there are no more points to be filled
  678. ; in and we've hit the bottom level of recursion
  679. ;
  680.                 push    bx
  681.         push    cx
  682.         call    CalcFrac
  683.                 pop     cx
  684.                 pop     bx
  685.                 sub     bl, cl
  686.                 push    bx
  687.         push    cx
  688.         call    CalcFrac
  689.                 pop     cx
  690.                 pop     bx
  691.                 sub     bh, cl
  692.                 push    bx
  693.         push    cx
  694.         call    CalcFrac
  695.                 pop     cx
  696.                 pop     bx
  697.                 add     bl, cl
  698.         call    CalcFrac
  699. OutCalcFrac:
  700.         ret
  701. CalcFrac    endp
  702. ;
  703. ; Shell for calling the calc fractal routine from C
  704. ;
  705. ; prototype: CalcFractal(unsigned seg)
  706. ;
  707. _CalcFractal    proc    far
  708.         seg = word ptr [bp + 6]
  709.         push    bp
  710.         mov    bp,sp
  711.         push    si
  712.         push    di
  713.         mov    es,[seg]
  714.         call    CalcFrac
  715.         pop    di
  716.         pop    si
  717.         pop    bp
  718.         ret
  719. _CalcFractal    endp
  720. ;;--------------------------Section End---------------------------
  721. ;
  722. ; Calculate the sky map
  723. ;
  724. ; modifies: everything
  725. ;
  726. ; prototype: void CalcSky(void)
  727. ;
  728. _CalcSky        proc    far
  729.         push    bp
  730.         push    si
  731.         push    di
  732.                 xor     di, di
  733.                 mov     es, [_Sky_Seg]
  734.                 stc
  735.         mov    eax, 0FFFFFFFFh  ; TAG
  736.                 mov     cx, 4000h    ; Set sky seg to all ffs ( color 255 = nothing drawn)
  737.                 rep     stosd            ; repeats 16384 times
  738.                 mov     si, [_RandomSeed]
  739.         call    RandomNumber
  740.         mov    [_RandomSeed],si
  741.                 xor     bx, bx              ; Start at offset 0
  742.                 mov     cx, 0100h        ; 8 levels of recursion
  743.                 mov     byte ptr es:[0080h], -2    ; Put in a couple of maximums
  744.                 mov     byte ptr es:[8000h], -2
  745.                 mov     byte ptr es:[0000h],  cl ; Put in a couple of minimums
  746.                 mov     byte ptr es:[8080h],  cl
  747.         call    CalcFrac        ; Calculate the sky colors
  748. ;
  749. ; Adjust the sky map colors
  750. ; into the sky palette
  751. ;
  752.                 xor     di, di
  753.   CalcSky1:
  754.                 mov     al, es:[di]
  755.                 shr     al, 2        ; Sky Color pointer
  756.         add    al,SkyPalette
  757.                 stosb
  758.                 or      di, di
  759.         jnz    CalcSky1
  760.         pop    di
  761.         pop    si
  762.         pop    bp
  763.         ret
  764. _CalcSky        endp
  765. ;
  766. ; Calculate the mountains
  767. ;
  768. ; modifies: everything
  769. ;
  770. ; Prototype: void CalcMountains(void)
  771. ;
  772. _CalcMountains    proc    far
  773.         push    bp
  774.         push    si
  775.         push    di
  776.                 mov     es, [_Map_Seg]  ;  CalcMap ??
  777.                 mov     fs, [_Color_Seg]
  778.         mov    eax,0ffffffffh
  779.         sub    di,di
  780.                 mov     cx, 4000h    ; Set the map to all ffffs
  781.         rep    stosd        ; 
  782.                 mov     si, [_RandomSeed]; Next random seed
  783.         call    RandomNumber
  784.                 mov     [_RandomSeed], si;
  785.                 xor     bx, bx          ; 
  786.                 mov     cx, 0100h    ; 256 decimal
  787.         mov    byte ptr es:[0000],40    ; Make an average sized mountain
  788.         call    CalcFrac    ; Calculate mountain heights
  789. ;
  790. ; Now average each point with three other nearby points to smooth out the
  791. ; mountains a little.
  792. ;
  793.                 xor     di, di
  794.   CalcMap1:
  795.                 xor     ax, ax
  796.                 mov     si, offset _MapCoord
  797.                 mov     bx, [si]
  798.                 add     al, es:[bx+di]
  799.                 adc     ah, ch
  800.                 inc     si
  801.                 inc     si
  802.                 mov     bx, [si]
  803.                 add     al, es:[bx+di]
  804.                 adc     ah, ch
  805.                 inc     si
  806.                 inc     si
  807.                 mov     bx, [si]
  808.                 add     al, es:[bx+di]
  809.                 adc     ah, ch
  810.                 inc     si
  811.                 inc     si
  812.                 mov     bx, [si]
  813.                 add     al, es:[bx+di]
  814.                 adc     ah, ch
  815.                 shr     ax, 2        ; Taking an average
  816.                 stosb
  817.                 or      di, di
  818.                 jnz     CalcMap1
  819. ;
  820. ; Set up map B.  This does the lighting effect from the right
  821. ;
  822.                 xor     si,si
  823.   CalcMap2:
  824.                 mov     al, es:[si]
  825.                 sub     al, es:[si+3]
  826.                 sbb     ah, ah
  827.                 add     ax, 20h    
  828.                 jns     CalcMap3
  829.                 xor     ax, ax
  830.   CalcMap3:
  831.                 cmp     al, 3Fh        ; Palette range 0-63
  832.                 jbe     CalcMap4
  833.                 mov     al, 3Fh
  834.   CalcMap4:
  835.         mov    fs:[si],al
  836.                 inc     si
  837.                 jnz     CalcMap2
  838. ;
  839. ; Another averager.  Average four points next to each other to
  840. ; smooth out some of the rough spots.
  841. ;
  842.   CalcMap5:
  843.                 xor     ax, ax
  844.                 add     al, es:[di]
  845.                 adc     ah, ch
  846.                 add     al, es:[di+0100h]    ; 256 decimal
  847.                 adc     ah, ch
  848.                 inc     di
  849.                 add     al, es:[di]
  850.                 adc     ah, ch
  851.                 add     al, es:[di+0100h]    ; 256 decimal
  852.                 adc     ah, ch
  853.                 dec     di
  854.                 shr     ax, 2        ; flattens plane (big = flat)
  855.                 stosb
  856.                 or      di, di
  857.                 jnz     CalcMap5
  858.         pop    di
  859.         pop    si
  860.         pop    bp
  861.                 ret
  862. _CalcMountains    endp
  863.  
  864. ;
  865. ; Calculate the X, Y , Z coordinates of our viewpoint
  866. ;
  867. ;
  868. ; Update the view coordinates
  869. ;
  870. ; Modifies: ax,bx,cx,dx, si
  871. ;
  872. ; prototype: void UpdateViewCoord(void)
  873. ;
  874. _UpdateViewCoord    proc    far
  875.         push    si
  876.                 mov     cx, [_Map_X]
  877.                 mov     dx, [_Map_Y]
  878. ; Calculate Z coordinate
  879. ;
  880.                 mov     es, [_Map_Seg]        ; Calculate New Points
  881.                 ror     cx, 4            ;; X_Pos / 16
  882.                 ror     dx, 4            ;; Y_Pos / 16
  883.                 mov     bl, cl                  ; bh,bl = y,x ( high 8 bits)
  884.                 mov     bh, dl
  885.                 shr     cx, 0Ch            ; cx = x low 4 bits
  886.                 shr     dx, 0Ch            ; dx = y low 4 bits
  887.                 push    dx
  888.                 inc     bl
  889.                 xor     ax, ax
  890.                 add     al, es:[bx]
  891.         dec    bl
  892.                 sub     al, es:[bx]
  893.                 sbb     ah, ah
  894.                 imul    cx
  895.                 mov     dx, ax            ; DX = dif in height * xlow4
  896.                 xor     ax, ax
  897.                 add     al, es:[bx]
  898.                 shl     ax, 4            
  899.                 add     ax, dx
  900.                 xchg    si, ax                  ; si = dx + height*16
  901.                 inc     bh                      ; move diagonally
  902.                 inc     bl                      ;
  903.                 xor     ax, ax
  904.                 add     al, es:[bx]
  905.         dec    bl
  906.                 sub     al, es:[bx]
  907.                 sbb     ah, ah
  908.                 imul    cx
  909.                 mov     dx, ax                  ; DX = dif in height * xlow4
  910.                 xor     ax, ax
  911.                 add     al, es:[bx]
  912.                 shl     ax, 4
  913.                 add     ax, dx            ; ax = dx + height * 16 - si
  914.                 pop     dx                      ;
  915.                 sub     ax, si                  ;
  916.                 imul    dx                      ; ax = ax * ylow4 + si*16
  917.                 shl     si, 4
  918.                 add     ax, si
  919.         pushf
  920.         cmp    [_FlyHeight], 0        ; are we flying ?
  921.         je    CalcNew0
  922.  
  923.         cmp    ah, [_FlyHeight]    ; are we flying below the
  924.         jae    CalcNew0    ; highest mountain ?
  925.         popf
  926.         mov    ah, [_FlyHeight]
  927.         jmp    CalcNew9
  928.   CalcNew0:
  929.         popf
  930. ;                add     ah, 1Ah    ; Offset us above the mountains a little ways
  931.                 add     ah, 14h    ; Offset us above the mountains a little ways
  932.                 jnc     CalcNew9
  933.                 mov     ax, 0FFFFh    ; 65535 decimal
  934.   CalcNew9:
  935.                 mov     [_MountHeight], ax        ; Checked
  936.         pop    si
  937.         ret
  938.  
  939. _UpdateViewCoord    endp
  940. ;;--------------------------Section End---------------------------
  941.  
  942. ;
  943. ; Draw the sky, scaling and making it diagonal (99 lines)
  944. ; Draw a line of color 50h
  945. ; Also draw the midband below the sky, give it a gradient ( 40 lines)
  946. ;
  947. ;;--------------------------Section Start-------------------------
  948. ;
  949. ; shift EDX:EAX right 15 with sign
  950. ;
  951. shiftright15    proc
  952.     mov    cx,15
  953. @srl:
  954.     sar    edx,1
  955.     rcr    eax,1
  956.     loop    @srl
  957.     ret
  958. shiftright15    endp
  959. ;
  960. ; Rotate one of the sky lines
  961. ;
  962. ; input:
  963. ;   eax = dist
  964. ; output;
  965. ;   bl:ax = x
  966. ;   bh:dx = y
  967. ;   DeltaX = delta for x
  968. ;   DeltaY = delta for y
  969.  
  970. rotate_skyline    proc
  971.     push    edi
  972.  
  973. ;
  974. ; Offset to sine table
  975. ;
  976.     mov    si,[_Angle]
  977.     shl    si,1
  978.     push    eax
  979. ;
  980. ; Calculate xcos(angle)
  981. ;
  982.     movsx    ebx,[si+costable]
  983.     imul    ebx
  984.     call    shiftright15
  985.     mov    edi,eax        ; edi = xcos(angle)
  986. ;
  987. ; Calculate xsin(angle)
  988.     pop    eax
  989.     movsx    ebx,[si+sintable]
  990.     imul    ebx
  991.     call    shiftright15
  992.     mov    esi,eax        ; esi = xsin(angle)
  993.  
  994. ;
  995. ; Calculate x' = xcos(angle)-ysin(angle)
  996. ;
  997.     mov    ecx,edi
  998.     sub    ecx,esi
  999. ;
  1000. ; Calculate y' = xsin(angle)+ycos(angle)
  1001. ;
  1002.     mov    edx,esi
  1003.     add    edx,edi
  1004. ;
  1005. ; DeltaX = Delta*cos(angle)
  1006. ;
  1007.     
  1008.     sar    edi,7        ; Scale down xcos(angle)
  1009.     mov    [DeltaX],edi
  1010. ;
  1011. ; DeltaY = Delta*sin(angle)
  1012. ;
  1013.      sar    esi,7        ; Scale down xsin(angle)
  1014.     mov    [DeltaY],esi    
  1015. ;
  1016. ; Up to now we've been doing relative rotation based around
  1017. ; (Map_X, Map_Y)
  1018. ;
  1019. ;
  1020. ; Offset X from where we are and load up bl:cx
  1021. ;    
  1022.     mov    eax,[SkyX]
  1023.     add    ecx,eax
  1024.     mov    ebx,ecx
  1025.     mov    cx,bx
  1026.     shr    ebx,16
  1027. ;
  1028. ; Offset Y from where we are and load up bh:dx
  1029. ;
  1030.     mov    eax,[SkyY]
  1031.     add    eax,edx
  1032.     mov    dx,ax
  1033.     shr    eax,16
  1034.     mov    bh,al
  1035.     
  1036. ;
  1037. ; load up bl:ax
  1038. ;
  1039.      mov    ax,cx
  1040.     pop    edi
  1041.     ret
  1042. rotate_skyline    endp
  1043. ;
  1044. ; Update the sky view
  1045. ;
  1046. ; modifies: everything
  1047. ;
  1048. ; prototype: void UpdateSky(void)
  1049. ;
  1050. _UpdateSky    proc    far
  1051.         push    si
  1052.         push    di
  1053.                 xor     eax, eax
  1054.         mov    ax,[_MountHeight]
  1055.         neg    ax              ; (- _MountHeight/8 + 16384)
  1056.                 shr     ax, 3
  1057.                 add     ah, 40h        ; 64 decimal   
  1058.                 shl     eax, 4          ; * 16
  1059.                 shl     eax, 9          ; *512
  1060.         mov    [SkyMountHeight],eax
  1061.                 xor     eax, eax
  1062.         mov    ax,[_Map_X]
  1063.                 shl     eax, 9          ; * 512
  1064.         mov    [SkyX],eax
  1065.                 xor     eax, eax
  1066.         mov    ax,[_Map_Y]
  1067.                 shl     eax, 9          ; *512
  1068.         mov    [SkyY],eax
  1069. ;
  1070. ; Now we scale the sky for distance and draw it
  1071. ;
  1072.                 mov     gs, [_Sky_Seg]    ; Point at sky data
  1073.         mov    ecx,63h
  1074.         sub    di,di
  1075.         mov    es,[_InternalScreen_Seg] ; Point at our screen
  1076.   @UpdateSky1:
  1077.         push    ecx
  1078.                 mov     eax, [SkyMountHeight]    ; Adjusted mountain height
  1079.                 xor     edx, edx        ;
  1080.                 div     ecx             ; Divided by number of lines left
  1081.         call    rotate_skyline
  1082. ;
  1083. ; Draw one line of the sky
  1084. ;
  1085.         mov    cx,256
  1086.  @usl:
  1087.         mov    si,bx
  1088.                 db      65h                 ; GS segment override prefix
  1089.                 movsb
  1090.         add    ax,word ptr [DeltaX]
  1091.         adc    bl,byte ptr [DeltaX+2]
  1092.         add    dx,word ptr [DeltaY]
  1093.         adc    bh,byte ptr [DeltaY +2]
  1094.         loop    @usl
  1095.         pop    ecx
  1096.                 loop     @UpdateSky1
  1097. ;
  1098. ;
  1099. ;
  1100.                 mov     eax, 50505050h        ; Draw a line of color 50h
  1101.                 mov     cx, 40h
  1102.                 rep     stosd            ; repeats 64 times
  1103.  
  1104. ;
  1105. ; Now draw the midband.  We don't need to rotate this, it is constant
  1106. ;
  1107.  
  1108.                 mov     si, [_MountHeight]
  1109.                 mov     bx, 04            ; Starting divisor
  1110.   @UpdateSky2:
  1111.                 mov     ax, si            ; Divide height by divisor
  1112.                 xor     dx, dx
  1113.                 div     bx
  1114.                 shr     ax, 7            ; And shift right to get color
  1115.                 cmp     al, 3Fh            ; 63 decimal
  1116.                 jbe     @UpdateSky3
  1117.                 mov     al, 3Fh            ; 63 decimal
  1118.   @UpdateSky3:
  1119.         add    al,MidbandPalette
  1120.                 mov     ah, al            ; Replicate color throughout EAX
  1121.                 mov     dx, ax
  1122.                 shl     eax, 10h
  1123.                 xchg    ax, dx
  1124.                 mov     cx, 40h            ; Draw a line of this color
  1125.                 rep     stosd            ; repeats 64 times
  1126.                 inc     bx            ; Next devisor
  1127.                 cmp     bx, 2Ch            ; Drawing 40 lines of this
  1128.                 jne     @UpdateSky2
  1129.         pop    di
  1130.         pop    si
  1131.         ret
  1132. _UpdateSky    endp
  1133.  
  1134. ;
  1135. ; Calculate the X, Y deltas for the angle we are moving at
  1136. ;
  1137. ; prototype void DeltaMove(int distance, int angle)
  1138. ;
  1139. ; angle MUST be in the range 0 - 359
  1140. ;
  1141.         angle = bp+8
  1142.         distance = bp+6
  1143. _DeltaMove    proc    far
  1144.         push    bp
  1145.         mov    bp,sp
  1146.         push    si
  1147. ;
  1148. ; Get the angle
  1149. ;
  1150.         mov    si,[angle]        ; Angle
  1151.         shl    si,1            ; Index into cos/sin tables
  1152.  
  1153. ;
  1154. ; x delta = x cos(angle)
  1155. ;
  1156.         movzx    eax,word ptr [distance]
  1157.         movsx    ebx,[si+costable]
  1158.         imul    ebx
  1159.         sar    eax,15
  1160.         add    [_Map_X],ax
  1161. ;
  1162. ; y delta = y cos(angle)
  1163. ;
  1164.         movzx    eax,word ptr [distance]
  1165.         movsx    ebx,[si+sintable]
  1166.         imul    ebx
  1167.         sar    eax,15
  1168.         add    [_Map_Y],ax
  1169.  
  1170.         pop    si
  1171.         pop    bp
  1172.         ret
  1173. _DeltaMove    endp
  1174. ;
  1175. ; Shift Right 16 times
  1176. ;
  1177. shiftright16    proc
  1178.         mov    cx,16
  1179. srl16:
  1180.         sar    edx,1
  1181.         rcr    eax,1
  1182.         loop    srl16
  1183.         ret
  1184. shiftright16    endp
  1185. ;
  1186. ; Shift Right 8 times
  1187. ;
  1188. shiftright10    proc
  1189.         mov    cx,10
  1190. srl10:
  1191.         sar    edx,1
  1192.         rcr    eax,1
  1193.         loop    srl10
  1194.         ret
  1195. shiftright10    endp
  1196. ;
  1197. ; Init Circle Coords
  1198. ;
  1199. ; input:
  1200. ;    si = radius
  1201. ; output:
  1202. ;   DeltaX, DeltaY, D , Xrel, Yrel, RfourthCsquared, TwoRcubedC  initted
  1203. init_coords    proc
  1204. ;
  1205. ; Calculate RC
  1206. ;
  1207.         movzx    eax,[_B]
  1208.         mul    esi
  1209.         call    shiftright16        ; We are keeping a 16-bit fraction
  1210.         mov    [RC],eax
  1211. ;
  1212. ; Calculate D = 5rfourthCsqaured/4-RfourthC
  1213. ;
  1214. ; This is rsqaured*csqaured
  1215.         mul    eax
  1216.         call    shiftright16
  1217.  
  1218. ;
  1219. ; This is RfourthCsquared
  1220. ;
  1221.         mul    esi
  1222.         call    shiftright16
  1223.         mul    esi
  1224.         call    shiftright16
  1225.         call    shiftright10        ; We shift the decision variables
  1226.                         ; to keep their values within
  1227.                         ; a 32-bit dword
  1228.         mov    [RfourthCsquared],eax
  1229.         mov    [TwoRfourthCsquared],eax
  1230.         shl    [TwoRfourthCsquared],1
  1231. ;
  1232. ; Times 5/4
  1233. ;
  1234.         mov    ebx,eax
  1235.         shl    ebx,2
  1236.         add    eax,ebx
  1237.         shr    eax,2
  1238.         mov    [D],eax
  1239. ;
  1240. ; This is RfourthC
  1241. ;
  1242.         mov    eax,[RC]
  1243.         mul    esi
  1244.         call    shiftright16
  1245.         mul    esi
  1246.         call    shiftright16
  1247.         call    shiftright10
  1248.         mul    esi
  1249.         call    shiftright16
  1250.         sub    [D],eax
  1251. ;
  1252. ; This is DeltaX = 2RfourthC
  1253. ;
  1254.         shl    eax,1
  1255.         mov    [DeltaX],eax
  1256. ;
  1257. ; This is Yrel & DeltaY
  1258. ;
  1259.         sub    eax,eax
  1260.         mov    [Yrel],eax
  1261.         mov    [DeltaY],eax
  1262. ;
  1263. ; This is Xrel
  1264. ;
  1265.         mov    [Xrel],esi
  1266.  
  1267.         ret
  1268. init_coords    endp        
  1269. ;
  1270. ; Calculate new circle coords and deltas and C
  1271. ;
  1272. calc_coords    proc
  1273.         bt    [D],31            ; Check sign of decision variable
  1274.         jc    nodeltax        ; If neg use old X
  1275.         mov    eax,[RC]    
  1276.         sub    [Xrel],eax          ; Else update X and decision vars
  1277.         mov    eax,[TwoRfourthCsquared]
  1278.         sub    [DeltaX],eax
  1279.         mov    eax,[DeltaX]
  1280.         sub    [D],eax
  1281. nodeltax:
  1282.         mov    eax,[RC]        ; Now update Y and decision vars
  1283.         add    [Yrel],eax
  1284.         mov    eax,[TwoRfourthCsquared]
  1285.         add    [DeltaY],eax
  1286.         mov    eax,[RfourthCsquared]
  1287.         add    [D],eax
  1288.         mov    eax,[DeltaY]
  1289.         add    [D],eax
  1290.         ret
  1291. calc_coords    endp
  1292. ;
  1293. ; Get absolute X,Y coords
  1294. ;
  1295. ; output:
  1296. ;    bl:cx = x coord
  1297. ;    bh:dx = y coord
  1298. ;
  1299. get_coords    proc
  1300. ;
  1301. ; Calculate X coord in bl:cx
  1302. ;
  1303.         mov    ecx,[Xpos]
  1304.         movzx    eax,[_Map_X]
  1305.         shl    eax,12
  1306.         add    ecx,eax
  1307.         mov    ebx,ecx        ; CX has X fraction
  1308.         sar    ebx,16        ; BL has X integer
  1309. ;
  1310. ; Calculate Y coord in bh:dx
  1311. ;
  1312.         mov    edx,[Ypos]
  1313.         movzx    eax,[_Map_Y]
  1314.         shl    eax,12
  1315.         add    edx,eax        ; DX has Y fraction
  1316.         mov    eax,edx        ;
  1317.         sar    eax,16        ; BH has Y integer
  1318.          mov    bh,al
  1319.  
  1320.         ret
  1321. get_coords    endp
  1322. ;
  1323.         
  1324. ; Draw a height at a point
  1325. ;
  1326. draw_height    proc
  1327.         push    dx
  1328.                 shr     cx, 1            ; Divide new fraction by 2
  1329.                 mov     al, fs:[bx+1]
  1330.                 sub     al, fs:[bx]
  1331.                 sbb     ah, ah
  1332.         imul    cx            ; height dif * fraction/128
  1333.                 shrd    ax, dx ,7        ;
  1334.                 add     ah, fs:[bx]        ; + current height
  1335.                 mul     [ReciprocalPerspective]        ; * 10000h / perspective scale
  1336.                 mov     di, [RelativeHeight]    ; Subtracted from r16b
  1337.                 sub     di, dx            ;
  1338.                 jns     @UpdateMountains5        ; If < 0 make -1
  1339.                 mov     di, 0FFFFh
  1340.   @UpdateMountains5:
  1341.                 cmp     di, 0C8h    ; See if fits on screen
  1342.                 jl      @UpdateMountains6
  1343.                 mov     di, 0C7h    ; If not force it to
  1344.   @UpdateMountains6:
  1345.                 mov     al, gs:[bx+1]        ; Height dif * upper part of fraction *2
  1346.                 sub     al, gs:[bx]        ;
  1347.         imul    ch            ;
  1348.                 shl     ax, 1            ;
  1349.                 add     ah, gs:[bx]             ; + height at current point
  1350.                 mov     dx, ax
  1351.                         ; Table A & B are used to correlate two 
  1352.                         ; different perspectives with each other
  1353.                 xchg    ax, [si+Table_B]    ; Distance to go before changing shades
  1354.                 mov     bp, di            ; Lines high in table A
  1355.                 xchg    bp, [si+Table_A]
  1356.                 sub     bp, di           ; Quit if distance to go < lines high
  1357.                 jns     @UpdateMountains7
  1358.                 shl     di, 8            ; Get y coord
  1359.                 add     di, [CurrentCol] ; + row,col of point
  1360.                 push    ax            ; 
  1361.                 sub     ax, dx                  ; (New dit to go - old dist to go)/lines high
  1362.         cwd
  1363.         idiv    bp
  1364.                 pop     dx            ; DX = dist to go
  1365.                 push    bx
  1366.                 lea     bx, [bp+1]        ; bh = (lines high + 1), bl = 0
  1367.                 shl     bx, 8
  1368. ;
  1369. ; Draw a vertical line
  1370. ;
  1371.   @uml:
  1372.                 mov     es:[bx+di], dh    ; 
  1373.                 add     dx, ax        ; 
  1374.                 inc     bh        ; 
  1375.         inc    bp   
  1376.         jnz    @uml
  1377.                 pop     bx
  1378.   @UpdateMountains7:
  1379.         pop    dx
  1380.                 shl     cx, 1
  1381.         ret
  1382. draw_height    endp
  1383. ;
  1384. ; Load reflect coords
  1385. ;
  1386. reflect_coords    proc
  1387.         mov    ecx,[Xrel]        ; Load up x,y coords
  1388.         mov    edx,[Yrel]        ;
  1389.         bt    [reflectswap],bx    ; See if have to swap this octant
  1390.         jnc    noswap            ;
  1391.         xchg    ecx,edx            ; Yes, do it
  1392. noswap:
  1393.         bt    [reflectnegx],bx    ; See if x is neg this octant
  1394.         jnc    nonegx
  1395.         neg    ecx            ; Yes, do it
  1396. nonegx:
  1397.         bt    [reflectnegy],bx    ; See if y is neg this octant
  1398.         jnc    nonegy
  1399.         neg    edx            ; Yes, do it
  1400. nonegy:
  1401.         mov    [Xpos],ecx        ; Save values of X&Y to use
  1402.         mov    [Ypos],edx
  1403.         mov    si,[intermedangletab+si]; Get the column to draw in
  1404.         mov    [CurrentCol],si    
  1405.         shr    [CurrentCol],1        ; column in table was table ofs    
  1406.         ret
  1407. reflect_coords    endp
  1408.     
  1409. ;
  1410. ; Reflect our lower 45 degree angle into appropriate quadrants
  1411. ;
  1412. reflect_angle    proc
  1413.         push    si
  1414.         mov    dx,si
  1415. ;
  1416. ; Copy the relevant octant angles to the intermediate table
  1417. ;
  1418.         push    es
  1419.         push    ds
  1420.         pop    es
  1421.         mov    cx,5            ; We can draw in up to five 
  1422.         mov    bx,[octant]        ; octants
  1423.         lea    si,[angletab + bx]    ; Select the first octant
  1424.         mov    di,offset intermedangletab ; Get local table
  1425. itc:
  1426.         lodsw                ; Get the base angle
  1427.         bt    bx,1            ; If octant number odd
  1428.                         ; we current si, 
  1429.         jc    itca
  1430.         sub    ax,dx               ; Else we subtract it
  1431.         jmp    short itcb    
  1432. itca:
  1433.         add    ax,dx
  1434. itcb:
  1435.         stosw                ; Save the local value
  1436.         xor    bl,2            ; Switch odd/even flag
  1437.         loop    itc            ;
  1438.         pop    es            ;
  1439.         xor    bl,2            ; Restore odd/even flag to orig
  1440.         shr    bl,1            ; state & make the table index
  1441.                         ; a straight octant number
  1442. ;
  1443. ; Check if drawing in first or fifth octants
  1444. ;
  1445.         sub    si,si            ; First relative octant
  1446.         push    bx            ; Save absolute octant
  1447.         mov    ax,[intermedangletab]    ; See whether reflecting
  1448.                         ; angle into fifth octant
  1449.         cmp    ax,512
  1450.         jc    firstoct        ;
  1451.         add    si,8            ; Yes, adjust octant ptrs
  1452.         add    bx,4            ;
  1453. firstoct:
  1454.         call    reflect_coords        ; Reflect coords for this octant
  1455.         call    get_coords        ; Get coords
  1456.         call    draw_height        ; Draw the height
  1457.         pop    bx                      ; Absolute octant
  1458.         sub    si,si            ; Relative octant = 0
  1459.         mov    cx,3            ; Drawing three octants
  1460. refloop:
  1461.         
  1462.         inc    si            ; Next octant
  1463.         inc    si            ;
  1464.         inc    bx            ;
  1465.         push    cx            ;
  1466.         push    bx            ;
  1467.         push    si            ;
  1468.         call    reflect_coords        ; Reflect coords into this octant
  1469.         call    get_coords        ; Translate coords to draw_height
  1470.                         ; Format
  1471.         call    draw_height        ; Draw the height
  1472.         pop    si
  1473.         pop    bx
  1474.         pop    cx
  1475.         loop    refloop            ; Loop till done
  1476.         pop    si
  1477.         ret
  1478. reflect_angle    endp
  1479. ;
  1480. ; Draw mountains
  1481. ;
  1482. ; prototype: void UpdateMountains(void)
  1483. ;
  1484.  
  1485. _UpdateMountains    proc    far
  1486.         push    bp
  1487.         push    si
  1488.         push    di
  1489.                 mov     fs, [_Map_Seg]        ; Get the map height seg
  1490.                 mov     gs, [_Color_Seg]        ; The map shading seg
  1491.         push    ds
  1492.         pop    es
  1493. ;
  1494. ; Fill tables with default
  1495. ;
  1496.                 mov     eax, 7D007D00h        ; Initialiae table a
  1497.                 mov     di, offset Table_A
  1498.                 mov     cx, 80h            ; 64 decimal
  1499.                 rep     stosd            ; repeats 64 times
  1500.                 xor     eax, eax
  1501.                 mov     di, offset Table_B       ; Initilaize table b
  1502.                 mov     cx, 80h    
  1503.                 rep     stosd            ; repeats 64 times
  1504. ;
  1505. ; Calculate norm angle in 512ths of a circle
  1506. ;
  1507.         mov    ax,[_Angle]        ; multiply by 4096/360
  1508.         mul    [AngleConv]        ;
  1509.         shr    ax,3            ; We want 512/360
  1510.         mov    [_NormAngle],ax        ; Save the angle
  1511. ;
  1512. ; Calculate angletab & octant
  1513. ;    
  1514.         mov    cx,12            ; 12 possible octants
  1515.         mov    bx,ax            ; The viewing angle in 512ths
  1516.         mov    si,offset baseangles    ; We are going to calculate drawing
  1517.         mov    di,offset angletab    ; angles based on the viewing angle
  1518.                         ; And the default drawing angle for
  1519.                         ; a 0 degree view
  1520. atc:
  1521.         lodsw                ; Get default
  1522.         add    ax,bx            ; Add in viewing angle
  1523.         shl    ax,1            ; Make it a TABLE_A /TABLE_B index
  1524.         stosw                ; Save custom value
  1525.         loop atc            ; Loop til done
  1526.         mov    [octant],0        ; Assume octant is 0
  1527. olp:
  1528.         sub    bx,64            ; Sub one octant ; 64/512 = 1/8
  1529.         jle    doneoctant        ; Quit if went under 0
  1530.         inc    [octant]        ; Else we are up an octant
  1531.         jmp    olp            ; Loop around
  1532. doneoctant:
  1533.         shl    [octant],1        ; Make the octant a table index
  1534.  
  1535.                 mov     [PerspectiveIndex], 78h        ; Initialze R16a to item 60
  1536.             ; This is scale factor pointer for perspective
  1537. ;
  1538. ; First calculate mountain height relative to horizon
  1539. ;
  1540.         mov    es, [_InternalScreen_Seg] ; The draw seg
  1541.   @UpdateMountains1:
  1542.                 movzx   esi, [PerspectiveIndex]        ; 
  1543.                 mov     si, [si+_MapMakeTable]    ; Get an item in map make tbl
  1544.                 shl     si, 4            ; *4
  1545.                 mov     ax, [_Map_Y]        ; Get low 4 bits of y coord
  1546.                 and     ax, 0Fh            ;
  1547.                 xor     al, 0Fh                 ; Invert them
  1548.                 add     si, ax                  ; Add them with map make table
  1549.                 mov     ax, [_MountHeight]    ; Divide mountain height by this
  1550.                 xor     dx, dx
  1551.         div    si
  1552.                 add     ax, 64h            ; Add 100 lines in
  1553.                 mov     [RelativeHeight], ax        ; This is r16B
  1554.                 cmp     [PerspectiveIndex], 2        ; if index was 2
  1555.                 jne     @UpdateMountains2
  1556.                 mov     [RelativeHeight], 7D00h    ; Set default values
  1557.                 mov     [ReciprocalPerspective], 0000h    ;
  1558.                 jmp     @UpdateMountains3
  1559.   @UpdateMountains2:
  1560.                 xor     ax, ax            ; Else divide new inde into 10000h
  1561.                 mov     dx, 1
  1562.         div    si
  1563.                 mov     [ReciprocalPerspective], ax;
  1564.   @UpdateMountains3:
  1565.         shl    esi,12
  1566.         call    init_coords        ; Initialize circle coords at (r,0)
  1567.                 mov     si, 0            ; First item
  1568.                         ; (Rotating counter-clockwise)
  1569. ;
  1570. ; Main draw loop, draws a line of mountains at given depth of view
  1571. ;
  1572.   @UpdateMountains4:
  1573.         call    reflect_angle        ; Reflect the x,y coord into
  1574.                         ; the viewed octants
  1575.         call    calc_coords        ; Calculate next point on circle
  1576.                 inc     si
  1577.                 inc     si
  1578.         cmp    si,63*2
  1579.                 jbe     @UpdateMountains4
  1580.                 sub     [PerspectiveIndex], 2        ; get next closes ROW depth POV
  1581.                 jnz     @UpdateMountains1
  1582.         pop    di
  1583.         pop    si
  1584.         pop    bp
  1585.         ret
  1586. _UpdateMountains    endp
  1587. _TEXT    ends
  1588.     end